package com.jushu.storbox.util.identity;

import java.io.RandomAccessFile;
import java.security.MessageDigest;

public class PartFileMD5Identity extends AbsFileIdentity {

	private static final int BUFFER_SIZE = 1024 * 64;
	
	private long partStart = 0;
	
	private long partLength = 0;
	
	private long partCount = 0;
	
	private long remainSize;
	
	byte[] tempBuffer = null;
	
	public PartFileMD5Identity(String filePath, long partStart, long partLength) {
		super(filePath);
		initParam(partStart, partLength);
	}
	
	public PartFileMD5Identity(String filePath, long partStart, long partLength, IidentityCallback callback) {
		super(filePath, callback);
		initParam(partStart, partLength);
	}
	
	private void initParam(long partStart, long partLength) {
		if(partStart < 0 || partLength < 0 
				|| partStart > innerFile.length()
				|| partStart > partLength) {
			throw new IllegalArgumentException("argument is invalied");
		}
		initPartParamters(partStart, partLength);
		computeBufferParamter();
	}

	private void initPartParamters(long partStart, long partLength) {
		this.partStart = partStart;
		this.partLength = partLength > innerFile.length() ? innerFile.length() : partLength;
	}

	private void computeBufferParamter() {
		remainSize = partLength % BUFFER_SIZE;
		partCount = partLength / BUFFER_SIZE;
	}

	@Override
	protected String doComputeIdentity() throws Exception {
		RandomAccessFile resourceFile = null;
		try {
			tempBuffer = new byte[1024 * 64];
			resourceFile = new RandomAccessFile(innerFile, "r");
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			resourceFile.seek(partStart);
			
			int len = -1;
			long currentProgress = 0;
			long oldProgress = 0;
			long progress = 0;
			for(long index = 0; index < partCount; index++) {
				len = resourceFile.read(tempBuffer, 0, BUFFER_SIZE);
				if(len == -1) {
					break;
				}
				messageDigest.update(tempBuffer, 0, len);
				currentProgress = len;
				oldProgress = currentProgress * 100 / innerFile.length();
				if ( progress != oldProgress) {
					progress = oldProgress;
					IdentityCallback.onProgress((int) progress,
							(long) currentProgress, innerFile.length());
				}
			}
			
			len = resourceFile.read(tempBuffer, 0, (int)remainSize);
			if(len > 0) {
				messageDigest.update(tempBuffer, 0, len);
				IdentityCallback.onProgress(100, innerFile.length(), innerFile.length());
			}
			identity = bytes2String(messageDigest.digest());
			tempBuffer = null;
		} finally {
			if(resourceFile != null) {
				resourceFile.close();
				resourceFile = null;
			}
		}
		return identity;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
